package com.halflife.comeElectricity.orderMng.order;

import cn.jiguang.common.utils.StringUtils;
import com.halflife.framework.dto.Result;
import com.halflife.comeElectricity.basic.address.*;
import com.halflife.comeElectricity.member.merchant.Merchant;
import com.halflife.comeElectricity.orderMng.cancel.CancelOrderController;
import com.halflife.comeElectricity.orderMng.order.dto.OrderDTO;
import com.halflife.comeElectricity.orderMng.order.dto.SiteDTO;
import com.halflife.comeElectricity.orderMng.order.vo.OrderVO;
import com.halflife.comeElectricity.orderMng.reFund.ReFundEnum;
import com.halflife.comeElectricity.orderMng.reFund.ReFundOrder;
import com.halflife.comeElectricity.orderMng.reFund.ReFundOrderRepository;
import com.halflife.pay.wxpay.AESUtil;
import com.halflife.pay.wxpay.WXPayAgent;
import com.halflife.shiro.utils.ShiroUtil;
import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.distance.DistanceUtils;
import com.spatial4j.core.shape.Rectangle;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jdom2.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by zhaoyf on 2018/2/12.
 */
@RestController
@RequestMapping("mc_order")
public class OrderController {
    private Logger log = LoggerFactory.getLogger(OrderController.class);
    @Resource
    private OrderService orderService;
    @Resource
    private OrderRepository orderRepository;
    @Resource
    private OrderExtRepository orderExtRepository;
    @Resource
    private AddressGroupRepository addressGroupRepository;
    @Resource
    private AddressController addressController;
    @Resource
    private ReFundOrderRepository reFundOrderRepository;
    @Resource
    private CancelOrderController cancelOrderController;

    @RequestMapping(value = "/notify.do", produces = "text/html;charset=UTF-8", method = {RequestMethod.POST})
    public void returnmsg(HttpServletRequest request, HttpServletResponse response) throws Exception {

        // 解析结果存储在HashMap
        Map<String, String> map = new HashMap<String, String>();
        InputStream inputStream = request.getInputStream();

        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();

        // 遍历所有子节点
        for (Element e : elementList) {
            map.put(e.getName(), e.getText());
        }

        log.debug("===return_code===" + map.get("return_code"));
        log.debug("===return_msg===" + map.get("return_msg"));
        log.debug("===out_trade_no===" + map.get("out_trade_no"));

        //验证签名的过程

        //判断是否支付成功
        if (map.get("return_code").equals("SUCCESS")) {

            /**
             *支付成功之后的业务处理
             */
            String orderId = map.get("out_trade_no");
            Order order = orderRepository.selectByPrimaryKey(Integer.valueOf(orderId));
            if (order != null && order.getStatus()==OrderEnum.NOPAY.m_orderStatus.byteValue()) {
                Order updateOrder = new Order();
                updateOrder.setId(order.getId());
                updateOrder.setStatus(OrderEnum.WAITTOGET.m_orderStatus.byteValue());
                updateOrder.setTime_end(map.get("time_end"));
                updateOrder.setTransaction_id(map.get("transaction_id"));
                orderRepository.updateByPrimaryKeySelective(updateOrder);
            }
            // 释放资源
            inputStream.close();
            inputStream = null;
            Writer out = response.getWriter();
            out.write("<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>");
            out.close();

        } else if (map.get("return_code").equals("FAIL")) {

            /**
             *支付失败后的业务处理
             */

            // 释放资源
            inputStream.close();

            inputStream = null;
        }


    }

    /**
     * 退款回掉函数
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/notify_.do", produces = "text/html;charset=UTF-8", method = {RequestMethod.POST})
    public void returnRefundmsg(HttpServletRequest request, HttpServletResponse response) throws Exception {

        // 解析结果存储在HashMap
        Map<String, String> map = new HashMap<String, String>();
        InputStream inputStream = request.getInputStream();

        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();
        // 遍历所有子节点
        for (Element e : elementList) {
            log.debug("====="+e.getName()+":"+e.getText());
            map.put(e.getName(), e.getText());
        }

        log.debug("===return_code===" + map.get("return_code"));
        log.debug("===return_msg===" + map.get("return_msg"));
        log.debug("===out_trade_no===" + map.get("out_trade_no"));

        //验证签名的过程

        //判断是否退款成功
        if (map.get("return_code").equals("SUCCESS")) {
            log.debug("===================退款成功==========================");
            /**
             *退款成功之后的业务处理
             */
            //获取加密信息
            String req_info = map.get("req_info");
            //解密信息
            String info = AESUtil.decryptData(req_info);
            //将解密数据转化为Map
            SAXBuilder builder = new SAXBuilder();

            Document doc = DocumentHelper.parseText(info);

            Element element = doc.getRootElement();
            List<Element> list = element.elements();
            for (Element e : list) {
                log.debug("====="+e.getName()+":"+e.getText());
                map.put(e.getName(), e.getText());
            }

            String refund_no = map.get("out_refund_no");
            ReFundOrder reFundOrder = reFundOrderRepository.selectByPrimaryKey(Integer.valueOf(refund_no));
            if (reFundOrder != null ) {

                if(!StringUtils.isEmpty(reFundOrder.getRefund_status())
                        && reFundOrder.getRefund_status().equals(new String().valueOf(ReFundEnum.PROCESS.m_orderStatus))){
                    ReFundOrder updateReFundOrder = new ReFundOrder();
                    updateReFundOrder.setId(reFundOrder.getId());
                    if (map.get("refund_status").equals("SUCCESS"))
                        updateReFundOrder.setRefund_status(new String().valueOf(ReFundEnum.SUCCESS.m_orderStatus));
                    else if (map.get("refund_status").equals("CHANGE"))
                        updateReFundOrder.setRefund_status(new String().valueOf(ReFundEnum.CHANGE.m_orderStatus));
                    else if (map.get("refund_status").equals("REFUNDCLOSE"))
                        updateReFundOrder.setRefund_status(new String().valueOf(ReFundEnum.REFUNDCLOSE.m_orderStatus));
                    if (!StringUtils.isEmpty(map.get("success_time")))
                        updateReFundOrder.setSuccess_time(map.get("success_time"));
                    if (!StringUtils.isEmpty(map.get("settlement_refund_fee")))
                        updateReFundOrder.setSettlement_refund_fee(Integer.parseInt(map.get("settlement_refund_fee")));
                    if (!StringUtils.isEmpty(map.get("refund_recv_accout")))
                        updateReFundOrder.setRefund_recv_accout(new String(map.get("refund_recv_accout").getBytes("GBK"),"UTF-8"));
                    reFundOrderRepository.updateByPrimaryKeySelective(updateReFundOrder);
                    // 释放资源
                    inputStream.close();
                    inputStream = null;
                    Writer out = response.getWriter();
                    out.write("<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>");
                    out.close();
                }
            } else if (map.get("return_code").equals("FAIL")) {
                log.debug("=================== 退款失败 ==========================");
                /**
                 *退款失败后的业务处理
                 */

                // 释放资源
                inputStream.close();
                inputStream = null;
            }

        }
    }

    @Value("${system.order.serviceMoney}")
    private String serviceMoney;

    @PostMapping("/add")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Map> add(@RequestBody OrderDTO orderDTO, HttpServletRequest request) {
        Merchant merchant = ShiroUtil.getMerchant(request);
        Map map = new HashMap();
        Order order = new Order();
        order.setMerchantId(merchant.getId());
        order.setMerchartName(merchant.getShopName());
        OrderExt orderExt = new OrderExt();
        BigDecimal money = new BigDecimal(this.serviceMoney);
        orderDTO.setServiceMoney(orderDTO.getAmount().add(orderDTO.getFee()).multiply(money).setScale(2,BigDecimal.ROUND_HALF_UP));
        try {
            orderDTO.convert(order, orderExt);
            List<AddressGroup> addrList = addressGroupRepository.selectByMerchantId(merchant.getId());
            //保留用户第一次常用路线 add by liuj3
            if (addrList.size() <= 0) {
                AddressVO v = new AddressVO();
                //推送出发地
                v.setStartPlace(new Address().getAddressBySiteDTO(orderDTO.getStartPlace()));
                //推送目的地List
                if (orderDTO.getDestination().size() > 0) {
                    List<Address> l = new ArrayList<Address>();
                    for (SiteDTO s : orderDTO.getDestination()) {
                        l.add(new Address().getAddressBySiteDTO(s));
                    }
                    v.setDestination(l);
                }
                addressController.add(v, request);
            }
            if ("JSAPI".equals(orderDTO.getPayType())){
                orderExt.setPayType("JSAPI");
            }else{
                orderExt.setPayType("APP");
            }

            orderService.add(order, orderExt);
        } catch (Exception e) {
            map.put("error", e.getMessage());
            log.error(e.getMessage(), e);
            e.printStackTrace();
            return new ResponseEntity<Map>(map, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        try {
            WXPayAgent agent = new WXPayAgent(order.getId().toString(), orderExt.getAmount().add(orderExt.getFee()).multiply(new BigDecimal("100")).intValue());
            if ("JSAPI".equals(orderDTO.getPayType())) {
                log.debug("0000000000000000000000000openid{}",orderDTO.getOpenId());
                map = agent.doGzhUnifiedOrder(orderDTO.getOpenId());
            }else {
                map = agent.doUnifiedOrder();
            }
            return new ResponseEntity<Map>(map, HttpStatus.OK);
        } catch (Exception e) {
            map.put("error", e.getMessage());
            log.error(e.getMessage(), e);
            return new ResponseEntity<Map>(map, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity<OrderExt> get(@PathVariable Integer id, HttpServletRequest request) {
        Order order = orderRepository.selectByPrimaryKey(id);
        OrderExt orderExt = orderExtRepository.selectByPrimaryKey(id);
        return new ResponseEntity<OrderExt>(orderExt, HttpStatus.OK);

    }

    @GetMapping("/vo/{id}")
    public ResponseEntity<OrderVO> getVObyId(@PathVariable Integer id, HttpServletRequest request) {
        OrderVO orderExt = orderExtRepository.selectVOById(id);
        return new ResponseEntity<OrderVO>(orderExt, HttpStatus.OK);

    }

    //获取订单管理列表 edit by liuj3
    @GetMapping("/list")
    @ResponseStatus(HttpStatus.CREATED)
    // public ResponseEntity<List<CancelOrder>> list(@RequestParam(value="id",defaultValue = "null") Integer id,
    public ResponseEntity<OrderCallBack> list(@RequestParam(value = "longitude", required = false) Integer longitude,
                                              @RequestParam(value = "latitude", required = false) Integer latitude,
                                              @RequestParam(value = "currentPage", defaultValue = "1") Integer currentPage,
                                              @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
                                              HttpServletRequest request) {
        //oper 分页类型 0-进行中订单 1-已完成订单 -1-已取消订单
        Merchant merchant = ShiroUtil.getMerchant(request);
        if (longitude != null && latitude != null) {
            int radius = 1;//千米
            SpatialContext geo = SpatialContext.GEO;
            Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt(
                    geo.makePoint(longitude, latitude), radius * DistanceUtils.KM_TO_DEG, geo, null);
            System.out.println(rectangle.getMinX() + "-" + rectangle.getMaxX());// 经度范围
            System.out.println(rectangle.getMinY() + "-" + rectangle.getMaxY());// 纬度范围
        }
        //推送分页Map参数
        HashMap<String, Object> param = new HashMap();
        param.put("currentPage", (currentPage - 1) * pageSize);
        param.put("pageSize", pageSize);
        param.put("merchantId", merchant.getId());
        int totalCount = orderRepository.selectCountOrderByPage(param);
        List<Order> list = orderRepository.selectOrderByPage(param);
        //创建返回对象
        OrderCallBack b = new OrderCallBack();
        //推送订单列表
        b.setList(list);
        //计算总页数
        int totalPage = totalCount / pageSize;
        if (totalCount % pageSize != 0)
            totalPage++;
        b.setTotalPage(totalPage);
        return new ResponseEntity<OrderCallBack>(b, HttpStatus.OK);
    }

    @PutMapping("/updateStatus/{orderId}")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity updateOrderStatus(@PathVariable Integer orderId, HttpServletRequest request) {

        Order o = this.orderRepository.selectByPrimaryKey(orderId);
        if (o != null) {
            // OrderEnum n = OrderEnum.getStatus(2);
            o.setStatus(OrderEnum.STARTED.m_orderStatus.byteValue());
            //记录出发时间
            OrderExt e = orderExtRepository.selectByPrimaryKey(o.getId());
            e.setStartOffTime(Calendar.getInstance().getTimeInMillis());
            this.orderExtRepository.updateByPrimaryKey(e);
        }
        this.orderRepository.updateByPrimaryKey(o);
        return new ResponseEntity(1, HttpStatus.OK);
    }

    /**
     * 生成取消訂單 並刪除訂單 add by liuj 20180514
     * @param orderId
     * @param request
     */
    @PutMapping("/generatorCancel/{orderId}")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity add(@PathVariable Integer orderId, HttpServletRequest request){
        Map map = new HashMap();
        try {
            BeanUtilsBean beanUtilsBean = new BeanUtilsBean();
            beanUtilsBean.getConvertUtils().register(new org.apache.commons.beanutils.converters.BigDecimalConverter(null), BigDecimal.class);
            //查詢訂單以及訂單詳情
            if(orderId!=null) {
                //获取订单
                Order order = orderRepository.selectByPrimaryKey(orderId);
                OrderExt orderExt = orderExtRepository.selectByPrimaryKey(order.getId());
                //创建退款订单对象 add by liuj3
                ReFundOrder reFundOrder = new ReFundOrder();
                reFundOrder.setCreateTime(Calendar.getInstance().getTimeInMillis());
                //微信订单号
                reFundOrder.setTransaction_id(order.getTransaction_id());
                //商户订单号 out_trade_no 为orderId
                reFundOrder.setOut_trade_no(new String().valueOf(order.getId()));
                reFundOrder.setRefund_status(new String().valueOf(ReFundEnum.PROCESS.m_orderStatus));
                if(orderExt.getFee()==null)
                    orderExt.setFee(new BigDecimal(0));
                if(orderExt.getAmount()==null)
                    orderExt.setAmount(new BigDecimal(0));
                reFundOrder.setTotal_fee(orderExt.getAmount().add(orderExt.getFee()).multiply(new BigDecimal("100")).intValue());
                reFundOrder.setRefund_fee(orderExt.getAmount().add(orderExt.getFee()).multiply(new BigDecimal("100")).intValue());
                reFundOrderRepository.insert(reFundOrder);
                log.debug("====退款订单id:"+reFundOrder.getId());
                //发起退款申请
                //调用初始化退款服务代理
                WXPayAgent agent = new WXPayAgent(order.getId().toString(), order.getTransaction_id(),
                        orderExt.getAmount().add(orderExt.getFee()).multiply(new BigDecimal("100")).intValue(),orderExt.getAmount().add(orderExt.getFee()).multiply(new BigDecimal("100")).intValue(),
                        reFundOrder.getId().toString(),"商户取消订单");
                String result = agent.doRefund(orderExt.getPayType());
                if (result != null) {
                    reFundOrder.setRefund_id(result);
                    reFundOrderRepository.updateByPrimaryKeySelective(reFundOrder);
                    Integer merchantId = order.getMerchantId();
                    Long createTime = order.getCreateTime();
                    cancelOrderController.add(order.getId());
//                    //插入通知
//                    if(merchantId!=null) {
//
//                        OrderMessage orderMessage = new OrderMessage();
//                        orderMessage.setMerchantId(merchantId);
//                        orderMessage.setStatus(OrderMessage.STATUS_NORMAL);
//                        orderMessage.setMemo("您于" + NavStatic.getDate(createTime) + "下的订单,已经被管理员取消,请在取消订单中查看退款状态.");
//                        orderMessage.setSpare("您于" + NavStatic.getDate(createTime) + "下的订单,已经被管理员取消,请在取消订单中查看退款状态.");
//                        orderMessageRepository.insert(orderMessage);
//                    }
                }
            }
            //return Result.Ok();
            return new ResponseEntity(1, HttpStatus.OK);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // return Result.No("系统异常");
            return new ResponseEntity(1, HttpStatus.EXPECTATION_FAILED);
        }
    }

    @PutMapping("")
    @ResponseStatus(HttpStatus.CREATED)
    public void update(@RequestBody OrderDTO orderDTO, HttpServletRequest request) throws Exception{
        Order order = new Order();
        OrderExt orderExt = new OrderExt();
        orderDTO.convert(order, orderExt);
        orderService.add(order, orderExt);

    }

    @DeleteMapping("/{id}")
    private Result deleteById(@PathVariable Integer id) {
        try {
            orderRepository.deleteByPrimaryKey(id);
            return Result.Ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.No("系统异常");
        }
    }


}
